#ifndef _b_stringh_
#define _b_stringh_

// bstring.h
//
// Binary string class

#include "geometry.h"        // Our data types

#include <vector>
#include <string>

namespace simple{
    //
    // BString
    //

    class BString
    {
    public:
        BString  ();
        ~BString ();

        BString            (const BString& src);
        BString& operator= (const BString& src);

        size_t              size    () const    { return _string.size();}
        const void*         base    () const    { return _string.c_str();}
        // Return pointer, and size of our data

        void                rewind  ()          { _offset = 0;}
        // Reset our output pointer to the beginning

        bool                eof     () const    { return _offset >= _string.size();}
        // Return true if the stream is at the end

        bool                match   () const    { return _match;}
        // Return true if all extraction resulted in a match between
        // the requested data type and the stored data type
        // 数据类型转化时可能导致数据已经被破坏。这里就是检测是否破坏了。

        const std::string&  str     () const    { return _string;}
        // Acess to our underlying string data


        // Insertion operators
        BString& operator<< (Pel8   b);
        BString& operator<< (Pel16  w);
        BString& operator<< (Pel32s l);
        BString& operator<< (Pel32  l);
        BString& operator<< (float  f);
        BString& operator<< (double d);
        BString& operator<< (const std::string& s);
        BString& operator<< (const BString& bstr);

        void append (const void* data, unsigned int size);

        // Extraction operators
        BString& operator>> (Pel8&   b);
        BString& operator>> (Pel16&  w);
        BString& operator>> (Pel32s& l);
        BString& operator>> (Pel32&  l);
        BString& operator>> (float&  f);
        BString& operator>> (double& d);
        BString& operator>> (std::string& s);
        BString& operator>> (BString& bstr);

        bool fetch (const void*& data, unsigned int& size);
        // 获得eData类型数据，填充到data，size为获得的大小。若类型不对，则返回false

        std::string dump ();
        // Ascii dump of data, from the current offset
        // 监视当前的数据,并按照指定格式输出.

    private:
        std::string  _string;
        unsigned int _offset;
        bool         _match;

        enum eTypes {eNone=0, ePel8=1, ePel16=2, ePel32s=3, ePel32=4,
                   eFloat=5, eDouble=6, eString=7, 
                   eData=8, eBstr=9};
        // Supported datatypes. These values can never be changed but
        // more can be added

        BString  (const void* data, unsigned int size);

        void add (eTypes type, const void* data, unsigned int size);
        // Add the specified data to our buffer

        const void* extract (eTypes& type);
        // Return a pointer to the next data type and return its type.
        // Returns null if you attempt to read past the end
        // 检查流中下一个成员的数据类型

        Pel8        readPel8   (const void* p);
        Pel16       readPel16  (const void* p);
        Pel32s      readPel32s (const void* p);
        Pel32       readPel32  (const void* p);
        float       readFloat  (const void* p);
        double      readDouble (const void* p);
        std::string readString (const void* p);
        // Read a particular quantity from our string.

        std::string dumpBString (unsigned int indent);
        // Text dump the contents from a single BString

    };

}

#endif // _b_stringh_

